<template>
	<div class="my-shape-box" :class="{ lock, hide }">
		<!-- 锚点 -->
		<template v-if="!hiddenPoint">
			<div
				:class="`shape-point ${point}`"
				v-for="(point, index) in select ? pointList : []"
				:key="index"
				:style="usePointStyle(point, index, item.orgConfig.attr, cursorResize)"
				@mousedown="useMousePointHandle($event, point, item.orgConfig.attr)"
			/>
		</template>

		<!-- X轴，Y轴 -->
		<div v-show="$store.chart.editCanvas.isDrag && select" style="position: absolute; top: -20px; left: 10px">
			{{ item.orgConfig.attr.x }},{{ item.orgConfig.attr.y }}
		</div>

		<slot></slot>

		<!-- 选中 -->
		<div class="shape-modal" :style="useSizeStyle(item.orgConfig.attr)">
			<div class="shape-modal-select" :class="{ active: select }" />
			<div class="shape-modal-change" :class="{ selectActive: select, hoverActive: hover }" />

			<div
				class="line"
				v-for="item in lineArr"
				:key="item"
				:class="[hover && lineselect.has(item) && 'visible']"
				:style="lineselect.get(item)"
			>
				<span class="my-absolute-center"> {{ lineselect.get(item)?.value }}</span>
			</div>
		</div>
	</div>
</template>

<script setup>
import { useSizeStyle, usePointStyle } from '@/utils';
import { useMousePointHandle } from '../../hooks/useDrag.hook';

const props = defineProps({
	item: {
		type: Object,
		required: true
	},
	hiddenPoint: {
		type: Boolean,
		required: false
	}
});

// 锚点
const pointList = ['t', 'r', 'b', 'l', 'lt', 'rt', 'lb', 'rb'],
	// 光标朝向
	cursorResize = ['n', 'e', 's', 'w', 'nw', 'ne', 'sw', 'se'],
	// 计算当前选中目标
	hover = computed(() => {
		if ($store.chart.isDrag) return false;
		if (props.item.status.lock) return false;
		return props.item.id === $store.chart.targetChart.hoverId;
	}),
	// 兼容多值场景
	select = computed(() => {
		if (props.item.status.lock) return false;
		return $store.chart.targetChart.selectId.find((e) => e === props.item.id);
	});

// 锁定
const lock = computed(() => props.item.status.lock),
	// 隐藏
	hide = computed(() => props.item.status.hide);

/************************************************************************* 相邻组件间距***************************************************/

import { max, min } from 'lodash';

const lineArr = ['top', 'right', 'bottom', 'left'],
	// * 线条集合
	lineselect = ref(new Map()),
	// * 当前目标
	{ selectId } = toRefs($store.chart.targetChart),
	selectTarget = computed(() => $store.chart.componentList[$store.chart.fetchTargetIndex()]),
	selectAttr = computed(() => selectTarget.value?.orgConfig.attr || {});

// * 监听鼠标移动
watch(
	() => $store.chart.mousePosition,
	throttle(() => {
		try {
			if (!$store.chart.editCanvas.isDrag || selectId.value.length !== 1) return;

			// 获取目标组件数据
			const selectW = selectAttr.value.w;
			const selectH = selectAttr.value.h;

			// 距离左侧
			const selectLeftX = selectAttr.value.x;
			const selectRightX = selectLeftX + selectW;

			// 距离顶部
			const selectTopY = selectAttr.value.y;
			const selectBottomY = selectTopY + selectH;

			lineselect.value.clear();

			// 循环查询所有组件数据
			const componentList = $store.chart.componentList.map((e) => ({
				id: e.id,
				attr: e.orgConfig.attr,
				parentId: e.parentId
			}));
			// 传入画布数据，计算上下左右相关组件
			const topArr = [],
				rightArr = [],
				bottomArr = [],
				leftArr = [];
			lineArr.forEach((lineItem) => {
				componentList.forEach((component) => {
					// 排除不计算的属性
					if (selectTarget.value.id === component.id) return;
					if (selectTarget.value.parentId && selectTarget.value.parentId != component.parentId) return;
					if (!selectTarget.value.parentId && component.parentId) return;

					const componentW = component.attr.w;
					const componentH = component.attr.h;
					// 距离左侧
					const componentLeftX = component.attr.x;
					const componentRightX = componentLeftX + componentW;
					// 距离顶部
					const componentTopY = component.attr.y;
					const componentBottomY = componentTopY + componentH;

					if (lineItem.includes('top')) {
						if (
							((componentLeftX <= selectLeftX && selectLeftX <= componentRightX) ||
								(selectRightX <= componentRightX && selectRightX >= componentLeftX) ||
								(componentLeftX > selectLeftX && componentRightX < selectRightX)) &&
							componentBottomY <= selectTopY
						) {
							topArr.push(componentBottomY);
						}
					}
					if (lineItem.includes('right')) {
						if (
							((componentTopY <= selectTopY && selectTopY <= componentBottomY) ||
								(selectBottomY <= componentBottomY && selectBottomY >= componentTopY) ||
								(componentTopY > selectTopY && componentBottomY < selectBottomY)) &&
							componentLeftX >= selectRightX
						) {
							rightArr.push(componentLeftX);
						}
					}
					if (lineItem.includes('bottom')) {
						if (
							((componentLeftX <= selectLeftX && selectLeftX <= componentRightX) ||
								(selectRightX <= componentRightX && selectRightX >= componentLeftX) ||
								(componentLeftX > selectLeftX && componentRightX < selectRightX)) &&
							componentTopY >= selectBottomY
						) {
							bottomArr.push(componentTopY);
						}
					}
					if (lineItem.includes('left')) {
						if (
							((componentTopY <= selectTopY && selectTopY <= componentBottomY) ||
								(selectBottomY <= componentBottomY && selectBottomY >= componentTopY) ||
								(componentTopY > selectTopY && componentBottomY < selectBottomY)) &&
							componentRightX <= selectLeftX
						) {
							leftArr.push(componentRightX);
						}
					}
				});
			});

			// 计算上下左右数据
			topArr.length &&
				lineselect.value.set('top', {
					top: `-${selectTopY - max(topArr)}px`,
					left: `${selectW / 2}px`,
					height: `${selectTopY - max(topArr)}px`,
					width: '2px',
					value: `${selectTopY - max(topArr)}px`
				});
			rightArr.length &&
				lineselect.value.set('right', {
					top: `${selectH / 2}px`,
					left: `${selectW}px`,
					width: `${min(rightArr) - selectRightX}px`,
					height: '2px',
					value: `${min(rightArr) - selectRightX}px`
				});
			bottomArr.length &&
				lineselect.value.set('bottom', {
					top: `${selectH}px`,
					left: `${selectW / 2}px`,
					height: `${min(bottomArr) - selectBottomY}px`,
					width: '2px',
					value: `${min(bottomArr) - selectBottomY}px`
				});
			leftArr.length &&
				lineselect.value.set('left', {
					top: `${selectH / 2}px`,
					left: `${-(selectLeftX - max(leftArr))}px`,
					width: `${selectLeftX - max(leftArr)}px`,
					height: '2px',
					value: `${selectLeftX - max(leftArr)}px`
				});
		} catch (err) {
			console.log(err);
		}
	}, 200),
	{
		deep: true
	}
);

// * 取消对齐线
watch(
	() => $store.chart.editCanvas.isDrag,
	(val) => {
		if (!val) {
			lineselect.value.clear();
		}
	}
);
</script>

<style lang="scss" scoped>
@include b(shape-box) {
	position: absolute;
	cursor: move;

	&.lock {
		cursor: default !important;
	}

	&.hide {
		display: none;
	}

	/* 锚点 */
	.shape-point {
		z-index: 1;
		position: absolute;
		width: 6px;
		height: 6px;
		border: 2px solid var(--el-color-primary);
		border-radius: 4px;
		background-color: #fff;
		transform: translate(-50%, -50%);
		&.t,
		&.b {
			width: 30px;
		}
		&.l,
		&.r {
			height: 30px;
		}
	}
	/* 选中 */
	.shape-modal {
		pointer-events: none;
		position: absolute;
		top: 0;
		left: 0;

		.line {
			z-index: 1;
			position: absolute;
			top: 0;
			left: 0;
			display: none;
			border: 1px dashed var(--el-color-info);
			color: var(--el-color-success);
			opacity: 0.7;
			&.visible {
				display: block;
			}
		}

		.shape-modal-select,
		.shape-modal-change {
			position: absolute;
			width: 100%;
			height: 100%;
			border-radius: 10px;
		}

		.shape-modal-select {
			opacity: 0.1;
			&.active {
				background-color: var(--el-color-primary);
			}
		}
		.shape-modal-change {
			border: 1px solid rgba(0, 0, 0, 0);
			&.selectActive,
			&.hoverActive {
				border-color: var(--el-color-primary);
			}
			&.hoverActive {
				border-style: dotted;
			}
			&.selectActive {
				border-style: solid;
			}
		}
	}
}
</style>
